#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <libusb-1.0/libusb.h>
#include <pthread.h>

/*
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass          239 Miscellaneous Device
  bDeviceSubClass         2 
  bDeviceProtocol         1 Interface Association
  bMaxPacketSize0        64
  idVendor           0x0525 Fuzhou Rockchip Electronics Company
  idProduct          0xa4a7 
  bcdDevice            0.01
  iManufacturer           1 
  iProduct                2 
  iSerial                 3 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0079
    bNumInterfaces          4
    bConfigurationValue     1
    iConfiguration          4 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              250mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass        224 Wireless
      bFunctionSubClass       1 Radio Frequency
      bFunctionProtocol       3 RNDIS
      iFunction               7 
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      3 RNDIS
      iInterface              5 
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 01
      ** UNRECOGNIZED:  04 24 02 00
      ** UNRECOGNIZED:  05 24 06 00 01
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               9
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              6 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              9 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN-------------------------> bulk1 host read
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT ---------------------> bulk1 host send
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             10 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN -----------------------> bulk2 host read
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT ---------------------> bulk2 host send
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0

*/


void device_Thread()
{
	int32_t ret; 
	int32_t ep1, ep2;
	int32_t actualLen, len;

	char sendbuf[] = "USB bulk device data ...";
	char readbuf[128] = {0};

	//device bulk 
	ep1 = open("/dev/usb-ffs/bulk2/ep1", O_RDWR);
	if (ep1 < 0)
	{ 
		printf("open ep1 failed, ret[%d]", ret);
		return -1;
	}

	ep2 = open("/dev/usb-ffs/bulk2/ep2", O_RDWR);
	if (ep2 < 0)
	{ 
		printf("open ep2 failed, ret[%d]", ret);
		return -1;
	}

	while(1)
	{
		memset(&readbuf[0], 0, sizeof(readbuf));
		//read
		actualLen = read(ep2, (uint8_t *)&readbuf[0], 128);
		if (actualLen < 0) 
		{
			printf("USB device read failed[%d]\n",actualLen);
		}
		else 
		{
			printf("USB device recive data\t\t[%s], \tlen[%d]\n", (uint8_t *)&readbuf[0], actualLen);
			//send
			actualLen = write(ep1, &sendbuf[0], strlen(sendbuf));
		}

		sleep(1);
	}

	close(ep1);
	close(ep2);

	return;
}

int main()
{
	int32_t ret; 
	int32_t actualLen, len;

	static pthread_t deviceThread = 0;

	struct libusb_device_handle *handle = NULL;

	char sendbuf[] = "USB bulk host data ...";
	char readbuf[128] = {0};

	ret = libusb_init(NULL);
	if (ret < 0)
	{
		printf("libusb_init failed\n");
		return -1;
	}

	handle = libusb_open_device_with_vid_pid(NULL, 0x0525, 0xa4a7);
	if (handle == NULL)
	{
		printf("libusb_open_device_with_vid_pid failed\n");
		return -1;
	}


	//check kernel active
  	if (libusb_kernel_driver_active(handle, 1) == 1)
  	{
    	printf("USB Kernel Driver Active \n");
 
    	if (libusb_kernel_driver_active(handle, 1) == 0)
    	{
      		printf("Kernel Driver Detached \n");
    	}
  	}
 
  	libusb_detach_kernel_driver(handle, 1);

	ret = libusb_claim_interface(handle, 1);//Num
	if (ret != LIBUSB_SUCCESS)
	{
		printf("libusb claim interface error, ret[%d]\n", ret);
		libusb_close(handle);
		return -1;
	}

	if (pthread_create(&deviceThread, NULL, device_Thread, NULL) != 0)
	{
		printf("create monitor task fail.\n");
		return -1;
	}

	while(1)
	{
		//read
		memset(&readbuf[0], 0, sizeof(readbuf));
		ret = libusb_bulk_transfer(handle, 0x84, &readbuf[0], 128, &actualLen, 50);
		if (0 == ret)
		{
			printf("USB host recive data\t\t[%s], \tread_len[%d]\n", &readbuf[0], actualLen);
		}

		sleep(2);

		ret = libusb_bulk_transfer(handle, 0x03, (uint8_t *) sendbuf, strlen(sendbuf), &actualLen, 50);
		if (ret < 0) 
		{
			printf("USB host send failed[%d]\n",ret);
		}
	}

	return 0;
}

